home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 20 / Cream of the Crop 20 (Terry Blount) (1996).iso / os2 / yeah09.zip / source / lib / ea.cpp next >
C/C++ Source or Header  |  1996-05-25  |  11KB  |  463 lines

  1. //------------------------------------------------------------
  2. //
  3. // Name:     ea.cpp
  4. // Version:  0.9
  5. // Author:   Björn Fahller.
  6. //
  7. // Copyright (C) Björn Fahller, 1996.
  8. //
  9. // Purpose:  Base class for extended attributes. The "engine" in
  10. //           YEAH.
  11. //
  12. // History:
  13. //          Ver.  Date         What
  14. //          0.9   1996-05-26   First official release.
  15. //
  16. //------------------------------------------------------------
  17.  
  18. #include <IString.hpp>
  19. #include <string.h>
  20. #include "YEA.H"
  21.  
  22.  
  23. #define INCL_DOSFILEMGR
  24. #include <os2.h>
  25.  
  26. #include <strstrea.h>
  27. #include <fstream.h>
  28. #include <IExcBase.hpp>
  29.  
  30. //////////////
  31. //
  32. // Prototypes of static functions.
  33. //
  34. //////////////
  35.  
  36. IEXCLASSIMPLEMENT(EAError, IException);
  37. IEXCLASSIMPLEMENT(EAReadError, EAError);
  38. IEXCLASSIMPLEMENT(EAWriteError, EAError);
  39. IEXCLASSIMPLEMENT(EATypeMismatchError, EAError);
  40.  
  41. static EA::CreatorMap defaultEAInit(void);
  42. void setupGEA(EAOP2* peaop2, const IString& name);
  43. EA* createFrom(EAOP2* peaop2, const EA::CreatorMap& cm);
  44. static char* prepareFEA(EAOP2* peaop2, const IString& name);
  45. static EA::NameSet nameset(ULONG type, PVOID p);
  46. static void defaultErrorHandler(EA::Error, ULONG);
  47.  
  48. //////////////
  49. //
  50. // Definition of class static variables
  51. //
  52. /////////////
  53.  
  54. inline EA::CreatorMap defaultEAInit(void)
  55. {
  56.   return EA::CreatorMap();
  57. }
  58.  
  59. EA::CreatorMap EA::defaultCreatorMap = defaultEAInit();
  60. void (*EA::errorHandler)(EA::Error, ULONG) = defaultErrorHandler;
  61.  
  62. /////////////
  63. //
  64. // Public methods
  65. //
  66. /////////////
  67.  
  68. EA::~EA(void)
  69. {
  70. }
  71.  
  72. void EA::getFrom(const IString& file, const IString& name)
  73. {
  74.   peaop2 = new EAOP2;
  75.   peaop2->fpGEA2List = (GEA2LIST*)new char[500];
  76.   peaop2->fpFEA2List = (FEA2LIST*)new char[65536];
  77.   ::setupGEA(peaop2, name);
  78.   APIRET rc = DosQueryPathInfo(file, FIL_QUERYEASFROMLIST, peaop2, sizeof(*peaop2));
  79.   if (rc)
  80.   {
  81.     delete peaop2->fpGEA2List;
  82.     delete peaop2->fpFEA2List;
  83.     delete peaop2;
  84.     peaop2 = 0;
  85.     errorHandler(ReadError, rc);
  86.     return;
  87.   }
  88.   feaproc();
  89.   delete peaop2->fpGEA2List;
  90.   delete peaop2->fpFEA2List;
  91.   delete peaop2;
  92.   peaop2 = 0;
  93. }
  94.  
  95. void EA::getFrom(fstreambase& file, const IString& name)
  96. {
  97.   peaop2 = new EAOP2;
  98.   peaop2->fpGEA2List = (GEA2LIST*)new char[500];
  99.   peaop2->fpFEA2List = (FEA2LIST*)new char[65536];
  100.   ::setupGEA(peaop2, name);
  101.   APIRET rc = DosQueryFileInfo(file.rdbuf()->fd(), FIL_QUERYEASFROMLIST, peaop2, sizeof(*peaop2));
  102.   if (rc)
  103.   {
  104.     delete peaop2->fpGEA2List;
  105.     delete peaop2->fpFEA2List;
  106.     delete peaop2;
  107.     peaop2 = 0;
  108.     errorHandler(ReadError, rc);
  109.     return;
  110.   }
  111.   feaproc();
  112.   delete peaop2->fpGEA2List;
  113.   delete peaop2->fpFEA2List;
  114.   delete peaop2;
  115.   peaop2 = 0;
  116. }
  117.  
  118. void EA::storeTo(const IString& file, const IString& name)
  119. {
  120.   peaop2 = new EAOP2;
  121.   peaop2->fpGEA2List = (GEA2LIST*)new char[500];
  122.   peaop2->fpFEA2List = (FEA2LIST*)new char[65536];
  123.  
  124.   setupFEA(name);
  125.   APIRET rc = DosSetPathInfo(file, FIL_QUERYEASIZE, peaop2, sizeof(*peaop2), 0);
  126.  
  127.   delete peaop2->fpGEA2List;
  128.   delete peaop2->fpFEA2List;
  129.   delete peaop2;
  130.   peaop2 = 0;
  131.  
  132.   if (rc)
  133.   {
  134.     errorHandler(WriteError, rc);
  135.   }
  136. }
  137.  
  138. void EA::storeTo(fstreambase& file, const IString& name)
  139. {
  140.   peaop2 = new EAOP2;
  141.   peaop2->fpGEA2List = (GEA2LIST*)new char[500];
  142.   peaop2->fpFEA2List = (FEA2LIST*)new char[65536];
  143.  
  144.   setupFEA(name);
  145.   APIRET rc = DosSetFileInfo(file.rdbuf()->fd(), FIL_QUERYEASIZE, peaop2, sizeof(*peaop2));
  146.  
  147.   delete peaop2->fpGEA2List;
  148.   delete peaop2->fpFEA2List;
  149.   delete peaop2;
  150.   peaop2 = 0;
  151.  
  152.   if (rc)
  153.   {
  154.     errorHandler(WriteError, rc);
  155.   }
  156. }
  157.  
  158.  
  159. /////////////
  160. //
  161. // Protected methods
  162. //
  163. /////////////
  164.  
  165. EA::EA(EA::Identifier anId)
  166.  : id(anId),
  167.    flags(0),
  168.    peaop2(0)
  169. {
  170. }
  171.  
  172. EA::EA(const EA& e)
  173.   : id(e.id),
  174.     flags(e.flags),
  175.     peaop2(0)
  176. {
  177. }
  178.  
  179. const EA& EA::operator=(const EA& e)
  180. {
  181.   id = e.id;
  182.   flags = e.flags;
  183.   return *this;
  184. }
  185.  
  186. /////////////
  187. //
  188. // Private methods
  189. //
  190. /////////////
  191.  
  192. void EA::setupFEA(const IString& name)
  193. {
  194.   char* p = ::prepareFEA(peaop2, name);
  195.   EAOP2& eaop2 = *peaop2;
  196.   ostrstream os(p, 65536-((char*)eaop2.fpFEA2List-p));
  197.   os.write((char*)&id, sizeof(id));
  198.   writeTo(os);
  199.   os.seekp(0, ios::end);
  200.   unsigned long length = os.tellp();
  201.   eaop2.fpFEA2List->list[0].cbValue = (USHORT)length;
  202.   eaop2.fpFEA2List->list[0].fEA = flags;
  203.   eaop2.fpFEA2List->cbList = length + p-(char*)eaop2.fpFEA2List;
  204.   if (eaop2.fpFEA2List->cbList % 4)
  205.   {
  206.     eaop2.fpFEA2List->cbList+= 4-(eaop2.fpFEA2List->cbList % 4);
  207.   }
  208. }
  209.  
  210.  
  211. void EA::feaproc(void)
  212. {
  213.   EAOP2& eaop2 = *peaop2;
  214.  
  215.   if (eaop2.fpFEA2List->list[0].cbValue == 0)
  216.   {
  217.     errorHandler(NoSuchEAError, 0);
  218.     return;
  219.   }
  220.   istrstream is(eaop2.fpFEA2List->list[0].szName+eaop2.fpFEA2List->list[0].cbName+1,
  221.                 eaop2.fpFEA2List->list[0].cbValue);
  222.  
  223.   Identifier type;
  224.   is.read((char*)(&type), sizeof(type));
  225.   if (type != id)
  226.   {
  227.     errorHandler(TypeMismatchError, type);
  228.     return;
  229.   }
  230.   flags = eaop2.fpFEA2List->list[0].fEA;
  231.   readFrom(is);
  232. }
  233.  
  234.  
  235. /////////////
  236. //
  237. // Static methods
  238. //
  239. /////////////
  240.  
  241. void EA::remove(const IString& file, const IString& name)
  242. {
  243.   EAOP2 eaop2;
  244.   eaop2.fpFEA2List = (FEA2LIST*)new char[1024];
  245.   eaop2.fpGEA2List = 0;
  246.   eaop2.oError = 0;
  247.   char* p = ::prepareFEA(&eaop2, name);
  248.   eaop2.fpFEA2List->list[0].cbValue = 0;
  249.   eaop2.fpFEA2List->list[0].fEA = 0;
  250.   eaop2.fpFEA2List->cbList = p-(char*)eaop2.fpFEA2List;
  251.   if (eaop2.fpFEA2List->cbList % 4)
  252.   {
  253.     eaop2.fpFEA2List->cbList+= 4-(eaop2.fpFEA2List->cbList % 4);
  254.   }
  255.   APIRET rc = DosSetPathInfo(file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), 0);
  256.   delete eaop2.fpFEA2List;
  257.   if (rc)
  258.   {
  259.     errorHandler(WriteError, rc);
  260.   }
  261. }
  262.  
  263. void EA::remove(fstreambase& file, const IString& name)
  264. {
  265.   EAOP2 eaop2;
  266.   eaop2.fpFEA2List = (FEA2LIST*)new char[1024];
  267.   eaop2.fpGEA2List = 0;
  268.   eaop2.oError = 0;
  269.   char* p = ::prepareFEA(&eaop2, name);
  270.   eaop2.fpFEA2List->list[0].cbValue = 0;
  271.   eaop2.fpFEA2List->list[0].fEA = 0;
  272.   eaop2.fpFEA2List->cbList = p-(char*)eaop2.fpFEA2List;
  273.   if (eaop2.fpFEA2List->cbList % 4)
  274.   {
  275.     eaop2.fpFEA2List->cbList+= 4-(eaop2.fpFEA2List->cbList % 4);
  276.   }
  277.   APIRET rc = DosSetFileInfo(file.rdbuf()->fd(), FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
  278.   delete eaop2.fpFEA2List;
  279.   if (rc)
  280.   {
  281.     errorHandler(WriteError, rc);
  282.   }
  283. }
  284.  
  285.  
  286. EA* EA::newFrom(const IString& file, const IString& name, const CreatorMap& cm)
  287. {
  288.   EAOP2 eaop2;
  289.   eaop2.oError = 0;
  290.   eaop2.fpFEA2List = (FEA2LIST*)new char[500];
  291.   eaop2.fpGEA2List = (GEA2LIST*)new char[65536];
  292.   ::setupGEA(&eaop2, name);
  293.   APIRET rc = DosQueryPathInfo(file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
  294.   if (rc)
  295.   {
  296.     delete eaop2.fpFEA2List;
  297.     delete eaop2.fpGEA2List;
  298.     errorHandler(ReadError, rc);
  299.     return 0;
  300.   }
  301.   EA* pea = createFrom(&eaop2, cm);
  302.   delete eaop2.fpFEA2List;
  303.   delete eaop2.fpGEA2List;
  304.   return pea;
  305. }
  306.  
  307. EA* EA::newFrom(fstreambase& file, const IString& name, const CreatorMap& cm)
  308. {
  309.   EAOP2 eaop2;
  310.   eaop2.oError = 0;
  311.   eaop2.fpFEA2List = (FEA2LIST*)new char[500];
  312.   eaop2.fpGEA2List = (GEA2LIST*)new char[65536];
  313.   ::setupGEA(&eaop2, name);
  314.   APIRET rc = DosQueryFileInfo(file.rdbuf()->fd(), FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
  315.   if (rc)
  316.   {
  317.     delete eaop2.fpFEA2List;
  318.     delete eaop2.fpGEA2List;
  319.     errorHandler(ReadError, rc);
  320.     return 0;
  321.   }
  322.   EA* pea = createFrom(&eaop2, cm);
  323.   delete eaop2.fpFEA2List;
  324.   delete eaop2.fpGEA2List;
  325.   return pea;
  326. }
  327.  
  328. EA::NameSet EA::namesIn(const IString& name)
  329. {
  330.   return nameset(ENUMEA_REFTYPE_PATH, (PVOID)(char*)name);
  331. }
  332.  
  333. EA::NameSet EA::namesIn(fstreambase& file)
  334. {
  335.   return nameset(ENUMEA_REFTYPE_FHANDLE, (PVOID)(file.rdbuf()->fd()));
  336. }
  337.  
  338. ////////////
  339. //
  340. // Static functions
  341. //
  342. ////////////
  343.  
  344. static EA::NameSet nameset(ULONG type, PVOID p)
  345. {
  346.   DENA2* pdena = (DENA2*)new char[65364];
  347.   pdena->oNextEntryOffset = 0;
  348.   pdena->cbValue = 0;
  349.   pdena->cbName = 0;
  350.   pdena->fEA = 0;
  351.   LONG count = -1;
  352.   APIRET rc = DosEnumAttribute(type, p, 1, (PVOID)pdena,